#include <bits/stdc++.h>

using namespace std;

/** *
 * 有 n 个序列（依次编号为 0,1,...,n−1），初始时各个序列都为空，你的任务是维护这 n 个序列，需要进行的各种操作的表示与意义如下：

1 i k x：在第 i 个序列的末尾插入 k 个值都为 x 的数；
2 i k：删除第 i 个序列末尾的 k 个数，若该序列已不足 k 个数，则删除序列中全部的数；
3 i：询问第 i 个序列的众数。
其中，一个序列的众数定义为该数列中出现次数最多的数，若出现次数最多的数有多种，取其中数值最小的数。

输入格式
从标准输入读入数据。

输入的第一行为两个正整数 n,q，表示序列的个数与操作次数。

接下来 q 行描述依次进行的操作，每行描述一个操作，每个操作的输入方式同题目描述。

对于所有输入数据，均满足 1 ≤ n ≤ 10^5, 1 ≤ q ≤ 10^6，
任何出现的序列编号 i 都满足 0 ≤ i <n，序列中出现的任何数值 x 均满足 0 ≤ x ≤ 10^9，
插入和删除操作中的数目 k 满足 1 ≤ k ≤ 10^9。
*/

namespace FastIO
{
    const int L = 1 << 20;
    char buffer[L], *S, *T;
    char obuf[L], *O = obuf;

    inline char Getchar()
    {
        if (S == T)
        {
            T = (S = buffer) + fread(buffer, 1, L, stdin);
            if (S == T)
                return EOF;
        }
        return *S++;
    }

    template <class T>
    inline void read(T &X)
    {
        char ch;
        T op = 1;
        X = 0;
        for (ch = Getchar(); ch > '9' || ch < '0'; ch = Getchar())
        {
            if (ch == '-')
                op = -1;
        }
        for (; ch >= '0' && ch <= '9'; ch = Getchar())
        {
            X = (X << 1) + (X << 3) + ch - '0';
        }
        X *= op;
    }

    inline void Putchar(char c)
    {
        if (O == obuf + L)
        {
            fwrite(obuf, 1, L, stdout);
            O = obuf;
        }
        *O++ = c;
    }

    template <class T>
    inline void write(T x)
    {
        if (x < 0)
        {
            Putchar('-');
            x = -x;
        }
        if (x > 9)
        {
            write(x / 10);
        }
        Putchar(x % 10 + '0');
    }

    // 在程序结束前调用，清空缓冲区
    struct Flusher
    {
        ~Flusher()
        {
            if (O != obuf)
            {
                fwrite(obuf, 1, O - obuf, stdout);
            }
        }
    } flusher;
} // namespace FastIO

using FastIO::Putchar;
using FastIO::read;
using FastIO::write;

class Squence
{
    // 序列的块 {数量, 值}
    vector<pair<long long, int>> blocks;
    // 每个值的总数 {值 -> 总数}
    unordered_map<int, long long> counts;
    // 众数候选 { {-总数, 值} }
    set<pair<long long, int>> modes;

    void update_count(int x, long long delta)
    {
        // 从 modes 中移除旧条目
        if (counts.count(x))
        {
            modes.erase({-counts[x], x});
        }

        // 更新总数
        long long new_count = counts[x] + delta;
        if (new_count > 0)
        {
            counts[x] = new_count;
            modes.insert({-new_count, x});
        }
        else
        {
            counts.erase(x);
        }
    }

public:
    void insert(long long k, int x)
    {
        if (k == 0)
            return;
        if (!blocks.empty() && blocks.back().second == x)
        {
            blocks.back().first += k;
        }
        else
        {
            blocks.push_back({k, x});
        }
        // 更新 x 的总数
        update_count(x, k);
    }

    void pop(long long k)
    {
        while (k > 0 && !blocks.empty())
        {
            auto &last_block = blocks.back();
            long long count = last_block.first;
            int value = last_block.second;

            if (k >= count)
            {
                update_count(value, -count);
                blocks.pop_back();
                k -= count;
            }
            else
            {
                update_count(value, -k);
                last_block.first -= k;
                k = 0;
            }
        }
    }

    int query()
    {
        if (modes.empty())
            return -1;
        return modes.begin()->second;
    }
};

vector<Squence> sq;

int main()
{
    // ios_base::sync_with_stdio(false);
    // cin.tie(0); cout.tie(0);

    int n;
    long long q;
    read(n);
    read(q);
    // cin >> n >> q;
    sq.resize(n);
    while (q--)
    {
        int t, i;
        long long k;
        int x;
        read(t);
        read(i);
        // cin >> t >> i;
        switch (t)
        {
        case 1:
            read(k);
            read(x);
            // cin >> k >> x;
            sq[i].insert(k, x);
            break;
        case 2:
            read(k);
            // cin >> k;
            sq[i].pop(k);
            break;
        case 3:
            write(sq[i].query());
            Putchar('\n');
            // cout << sq[i].query() << "\n";
            break;
        default:
            break;
        }
    }
    return 0;
}